import os.path
import re

from django.http import FileResponse
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet
from rest_framework_simplejwt.exceptions import TokenError, InvalidToken
from rest_framework_simplejwt.views import TokenObtainPairView

from python_shopping.settings import MEDIA_ROOT
from users.models import User, Addr
from rest_framework import mixins

from users.permissions import IsOwnerOrReadOnly
from users.serializers import UserSerializer, AddrSerializer


class AddrView(GenericViewSet, mixins.CreateModelMixin, mixins.ListModelMixin, mixins.DestroyModelMixin,
               mixins.UpdateModelMixin):
    '''收货地址管理视图'''
    queryset = Addr.objects.all()
    serializer_class = AddrSerializer
    # 设置认证用户才能有权限进行访问
    permission_classes = [IsAuthenticated]

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        # 通过请求过来的认证用户进行过滤
        queryset = queryset.filter(user=request.user)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    def set_default_addr(self, request, *args, **kwargs):
        '''设置默认的收货地址'''
        # 1.获取到要设置的地址对象
        obj = self.get_object()
        obj.is_default = True
        obj.save()
        # 2.将地址设置为默认的收货地址，将用户的其他收货地址设置为非默认
        # 获取用户收货地址
        queryset = self.get_queryset().filter(user=request.user)
        for item in queryset:
            if item != obj:
                item.is_default = False
                item.save()
        return Response({'message': '设置成功'}, status=status.HTTP_200_OK)


class FileView(APIView):
    """获取文件的视图"""

    def get(self, requests, name):
        path = MEDIA_ROOT / name
        if os.path.isfile(path):
            return FileResponse(open(path, 'rb'))
        return Response({'error': "没有找到该文件！"}, status=status.HTTP_404_NOT_FOUND)


class UserView(GenericViewSet, mixins.RetrieveModelMixin):
    """用户相关操作的视图集"""
    queryset = User.objects.all()
    serializer_class = UserSerializer
    # 设置认证用户才能有权限进行访问
    permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]

    # 用户上传头像的方法
    def upload_avatar(self, request, *args, **kwargs):
        avatar = request.data.get('avatar')
        # 校验是否上传文件
        if not avatar:
            return Response({'error': '上传失败，文件不能为空'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        # 检验文件的大小
        if avatar.size > 1024 * 1024:
            return Response({'error': '上传失败，文件过大不能超过300kb'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        # 保存文件
        user = self.get_object()
        # 获取序列化对象
        ser = self.get_serializer(user, data={'avatar': avatar}, partial=True)
        # 校验
        ser.is_valid(raise_exception=True)
        ser.save()
        return Response({'url': ser.data['avatar']})


class RegisterView(APIView):
    '''注册的接口'''

    def post(self, request):
        # 接受用户的参数
        username = request.data.get('username')
        password = request.data.get('password')
        email = request.data.get('email')
        password_confirmation = request.data.get('password_confirmation')
        # 参数的校验
        # 1.校验参数是否为空
        if not all([username, password, email, password_confirmation]):
            return Response({'error': '所有的参数不能为空'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        # 2.校验用户名是否已经注册
        if User.objects.filter(username=username).exists():
            return Response({'error': '用户名已经存在'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        # 3.校验两次密码是否一致
        if password != password_confirmation:
            return Response({'error': '两次密码不一致'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        # 4.校验密码长度
        if not (6 <= len(password) <= 8):
            return Response({'error': '密码长度必须在6-8位之间'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        # 5.校验邮箱是否存在
        if User.objects.filter(email=email).exists():
            return Response({'error': '该邮箱已经被使用'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        # 6.校验邮箱格式是否正确
        if not re.match(r'^[a-z0-9][\w.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return Response({'error': '邮箱格式不正确'}, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        # 创建用户
        obj = User.objects.create_user(username=username, password=password, email=email)
        res = {'username': username, 'id': obj.id, 'email': email}
        return Response(res, status=status.HTTP_201_CREATED)


class LoginView(TokenObtainPairView):
    """用户登录视图"""

    def post(self, request: Request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        try:
            serializer.is_valid(raise_exception=True)
        except TokenError as e:
            raise InvalidToken(e.args[0])
        # 自定义登录成功之后返回的结果
        result = serializer.validated_data
        result['id'] = serializer.user.id
        result['mobile'] = serializer.user.mobile
        result['email'] = serializer.user.email
        result['username'] = serializer.user.username
        result['token'] = result.pop('access')
        return Response(result, status=status.HTTP_200_OK)
